﻿using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Xml;
using SHomeWorkshop.LunarPresentation.Interfaces;
using SHomeWorkshop.LunarPresentation.Widegets;
using WPF = System.Windows.Controls;

namespace SHomeWorkshop.LunarPresentation.Expressions
{
    public class Grid : Expression, ICollapsed
    {
        public Grid(SubPanel rootPanel, SubPanel parentPanel, Editor editor) :
            base(rootPanel, parentPanel, editor)
        {
            this.baseGrid = new WPF.Grid() { Margin = cMargin };
            this.mainBorder.Child = this.baseGrid;
            this.subPanels = new List<SubPanel>();

            //this.baseGrid.RowDefinitions.Add(new WPF.RowDefinition());
            //this.baseGrid.ColumnDefinitions.Add(new WPF.ColumnDefinition());

            this.chineseName = "网格式";
            this.borderColor = null;
        }

        private static Thickness cMargin = new Thickness(1);

        private static Thickness noMargin = new Thickness(0);

        private WPF.Grid baseGrid;

        public WPF.Grid BaseGrid
        {
            get { return baseGrid; }
        }

        private int linesCount = 1;

        public int LinesCount
        {
            get { return linesCount; }
            set
            {
                if (value >= 1)
                {
                    linesCount = value;
                    this.XmlData.SetAttribute("LinesCount", linesCount.ToString());

                    UpdateRowDefinitions(value);
                }
            }
        }

        private int columnsCount = 1;

        public int ColumnsCount
        {
            get { return columnsCount; }
            set
            {
                if (value >= 1)
                {
                    columnsCount = value;
                    this.XmlData.SetAttribute("ColumnsCount", columnsCount.ToString());

                    UpdateColumnDefinitions(value);
                }
            }
        }

        private void UpdateColumnDefinitions(int columCount)
        {
            if (this.baseGrid == null) return;

            int c = this.baseGrid.ColumnDefinitions.Count;
            if (c == columCount) return;

            if (c > columCount)
            {
                this.baseGrid.ColumnDefinitions.RemoveRange(columCount, c - columCount);
            }
            else if (c < columCount)
            {
                for (int i = c; i < columCount; i++)
                {
                    this.baseGrid.ColumnDefinitions.Add(new WPF.ColumnDefinition());
                }
            }
        }

        private void UpdateRowDefinitions(int rowCount)
        {
            if (this.baseGrid == null) return;

            int c = this.baseGrid.RowDefinitions.Count;
            if (c == rowCount) return;

            if (c > rowCount)
            {
                this.baseGrid.RowDefinitions.RemoveRange(rowCount, c - rowCount);
            }
            else if (c < rowCount)
            {
                for (int i = c; i < rowCount; i++)
                {
                    this.baseGrid.RowDefinitions.Add(new WPF.RowDefinition());
                }
            }
        }

        public GridPanel GetGridPanel(int gridX, int gridY)
        {
            foreach (UIElement ue in this.baseGrid.Children)
            {
                GridPanel p = ue as Expressions.GridPanel;

                if (p != null && p.GridX == gridX && p.GridY == gridY)
                {
                    return p;
                }
            }

            return null;
        }

        public override SubPanel FirstSubPanel
        {
            get { return GetGridPanel(0, 0); }
        }

        public override SubPanel LastSubPanel
        {
            get
            {
                GridPanel gp = GetGridPanel(ColumnsCount - 1, LinesCount - 1);
                if (gp == null) return null;

                if (gp.MergeStanding == GridPanel.Standing.Slave)
                {
                    // 右下角这个子面板不可能合并其它子面板。
                    return gp.MasterGridPanel;
                }
                else return gp;
            }
        }

        protected override void BuildChildren()
        {
            base.BuildChildren();

            if (XmlData == null) return;

            //全部清空。再重建。
            baseGrid.Children.Clear();
            this.subPanels.Clear();

            XmlAttribute aLinesCount = this.XmlData.GetAttribute("LinesCount");
            XmlAttribute aColumnCount = this.XmlData.GetAttribute("ColumnsCount");

            if (aLinesCount != null)
            {
                this.LinesCount = int.Parse(aLinesCount.Value);
            }

            if (aColumnCount != null)
            {
                this.ColumnsCount = int.Parse(aColumnCount.Value);
            }

            XmlNodeList panelNodes = this.XmlData.SelectNodes("Expression");
            foreach (XmlNode node in panelNodes)
            {
                if (node.GetAttributeString("Type")
                    == TypeOfExpression.GridPanel.ToString())
                {
                    XmlAttribute aGridX = node.GetAttribute("GridX");
                    XmlAttribute aGridY = node.GetAttribute("GridY");
                    XmlAttribute aGridXSpan = node.GetAttribute("GridXSpan");
                    XmlAttribute aGridYSpan = node.GetAttribute("GridYSpan");

                    GridPanel gp = new GridPanel(
                        this.RootPanel, this.ParentPanel, this.Editor, this);

                    gp.XmlData = node;
                    baseGrid.Children.Add(gp);
                    this.subPanels.Add(gp);

                    if (aGridX != null) gp.GridX = int.Parse(aGridX.Value);
                    if (aGridY != null) gp.GridY = int.Parse(aGridY.Value);
                    if (aGridXSpan != null) gp.GridXSpan = int.Parse(aGridXSpan.Value);
                    if (aGridYSpan != null) gp.GridYSpan = int.Parse(aGridYSpan.Value);
                }
            }

            RefreshDefBorderColor();

            //普通网格式需要较大的内部空间，这样网格线会较好看；
            //而“行”则不需要，所以提供这个属性。
            XmlAttribute attrNoMargin = this.XmlData.GetAttribute("NoMargin");
            if (attrNoMargin != null && attrNoMargin.Value.ToLower() == "true")
            {
                this.baseGrid.Margin = noMargin;
            }

            XmlAttribute attrIsCollapsed = this.XmlData.GetAttribute("IsCollapsed");
            if (attrIsCollapsed != null)
            {
                this.isCollapsed = bool.Parse(attrIsCollapsed.Value);
                this.RefreshIsCollapsed();
            }
        }

        private void RefreshDefBorderColor()
        {
            XmlAttribute attrBorderColor = this.XmlData.GetAttribute("BorderColor");
            if (attrBorderColor == null)
            {
                //Binding borderBinding = new Binding();
                //borderBinding.Source = this.Editor.DefaultForeground;
                //this.mainBorder.SetBinding(Border.BorderBrushProperty, borderBinding);

                //考虑到“行”不需要自动以前景色的方式出现。
                //且未找到“取消绑定”的办法。此处未使用“绑定”来实现。
                //更改编辑器“默认前景色”后，将使用递归来实现“自动边框前景色”的更新。
                if (this.editor != null)
                {
                    this.mainBorder.BorderBrush = this.Editor.DefaultForeground;
                }
            }
            else
            {
                Brush resultBsh = ColorPicker.GetBrushByName(attrBorderColor.Value);
                if (resultBsh == null)
                {
                    this.borderColor = null;
                    this.mainBorder.BorderBrush = editor.DefaultForeground;
                }
                else
                {
                    this.mainBorder.BorderBrush = resultBsh;
                }
            }
        }

        /// <summary>
        /// 插入行。
        /// </summary>
        /// <param name="gridPanel">表示插入基准位置的子面板，索引值从0开始算。</param>
        /// <param name="atTop">是否在顶侧插入。默认为真。</param>
        public bool InsertLine(GridPanel gridPanel, ModifingItem mi, bool atTop = true)
        {
            if (gridPanel == null) return false;

            Action actLinesCount = new Action(this.ExID, -1, this.GetType().Name,
                "LinesCount", LinesCount.ToString(), (LinesCount + 1).ToString());

            LinesCount += 1;

            mi.Add(actLinesCount);

            int newLineIndex = gridPanel.GridY;
            if (atTop == false)
            {
                // 在当前行底侧插入新行。
                newLineIndex = newLineIndex + gridPanel.GridYSpan;
            }

            foreach (UIElement ue in baseGrid.Children)
            {
                GridPanel gp = ue as GridPanel;

                if (gp != null && gp.GridY >= newLineIndex)
                {
                    Action actGridY = new Action(gp.ExID, -1, gp.GetType().Name,
                        "GridY", gp.GridY.ToString(), (gp.GridY + 1).ToString());
                    gp.GridY += 1;

                    mi.Add(actGridY);
                }// 腾出空的行索引。
            }

            //按照基准行索引插入新行中每一个单元格。
            for (int i = 0; i < columnsCount; i++)
            {
                this.XmlData.LastChild.InsertXml(
                    LunarPresentation.Properties.Resources.GridPanel);

                GridPanel gp = new GridPanel
                    (this.RootPanel, ParentPanel, this.Editor, this)
                    {
                        XmlData = XmlData.LastChild,
                        GridY = newLineIndex,
                        GridX = i
                    };

                Action actInsertGridPanel = new Action(gp.ExID, baseGrid.Children.IndexOf(gp),
                    gp.GetType().Name, "InsertGridPanel",
                    null, gp.XmlData.OuterXml, ActionType.InsertGridPanel,
                    this.ExID);
                Action actGridY = new Action(gp.ExID, -1, gp.GetType().Name,
                    "GridY", gp.GridY.ToString(), newLineIndex.ToString());
                Action actGridX = new Action(gp.ExID, -1, gp.GetType().Name,
                    "GridX", gp.GridX.ToString(), i.ToString());
                mi.Add(actInsertGridPanel);
                mi.Add(actGridY);
                mi.Add(actGridX);

                baseGrid.Children.Add(gp);
                subPanels.Add(gp);
            }

            // 先取原位置这一行的各子面板。
            for (int ic = 0; ic < columnsCount; ic++)
            {
                //遍历每一列中每一个合并单元格。
                for (int il = 0; il < linesCount; il++)
                {
                    GridPanel gp = GetGridPanel(ic, il);
                    if (gp.MergeStanding == GridPanel.Standing.Master)
                    {
                        if (gp.GridY < newLineIndex &&
                            gp.GridY + gp.GridYSpan - 1 >= newLineIndex)
                        {
                            GridPanel newBrother = GetGridPanel(ic, newLineIndex);

                            Action actMergeStanding = new Action(newBrother.ExID, -1,
                                newBrother.GetType().Name, "MergeStanding",
                                newBrother.MergeStanding.ToString(),
                                GridPanel.Standing.Slave.ToString());

                            Action actMasterX = new Action(newBrother.ExID, -1, newBrother.GetType().Name,
                                "MasterX", newBrother.MasterX.ToString(), gp.GridX.ToString());

                            Action actMasterY = new Action(newBrother.ExID, -1, newBrother.GetType().Name,
                                "MasterY", newBrother.MasterY.ToString(), gp.GridY.ToString());

                            Action actGridYSpan = new Action(gp.ExID, -1, gp.GetType().Name,
                                "GridYSpan", gp.GridYSpan.ToString(), (gp.GridYSpan + 1).ToString());

                            newBrother.MergeStanding = GridPanel.Standing.Slave;
                            newBrother.MasterX = gp.GridX;
                            newBrother.MasterY = gp.GridY;
                            gp.GridYSpan += 1;

                            mi.Add(actMergeStanding);
                            mi.Add(actMasterX);
                            mi.Add(actMasterY);
                            mi.Add(actGridYSpan);

                            break;
                        }
                    }
                }
            }

            Editor.IsModified = true;
            return true;
        }

        public override void UpdateAlignment()
        {
            if (ParentPanel != null)// 子面板本身是不需要考虑对齐方式的。
            {
                if (ParentPanel.Direction == Orientation.Horizontal)
                {
                    switch (align)
                    {
                        case Alignment.LeftOrTop:
                            {
                                this.VerticalAlignment = VerticalAlignment.Top; break;
                            }
                        case Alignment.Center:
                            {
                                this.VerticalAlignment = VerticalAlignment.Center; break;
                            }
                        case Alignment.RightOrBottom:
                            {
                                this.VerticalAlignment = VerticalAlignment.Bottom; break;
                            }
                        default:
                            {
                                if (ParentPanel == this.RootPanel)
                                {
                                    this.VerticalAlignment = VerticalAlignment.Top;
                                    // 当前公式在根面板中。
                                    // 根面板水平对齐时，则默认并不按居中，而是按Top对齐。
                                }
                                else
                                {
                                    this.VerticalAlignment = VerticalAlignment.Center;
                                    // 水平子面板中的公式，默认居中对齐。
                                }
                                break;
                            }
                    }
                }
                else if (ParentPanel.Direction == Orientation.Vertical)
                {
                    switch (align)
                    {
                        case Alignment.LeftOrTop:
                            {
                                this.HorizontalAlignment = HorizontalAlignment.Left; break;
                            }
                        case Alignment.Center:
                            {
                                this.HorizontalAlignment = HorizontalAlignment.Center; break;
                            }
                        case Alignment.RightOrBottom:
                            {
                                this.HorizontalAlignment = HorizontalAlignment.Right; break;
                            }
                        default:
                            {
                                this.HorizontalAlignment = HorizontalAlignment.Stretch; break;
                                // 垂直子面板中的公式，默认左对齐。
                            }
                    }
                }

                //只有左齐时才支持，其它方式对齐要取消编号，水平子面板也要取消。
                //因此要在此处刷新。
                ParentPanel.RefreshAutoNumbersOfBaseText();
            }
        }

        /// <summary>
        /// 插入列。
        /// </summary>
        /// <param name="gridPanel">表示插入基准位置的子面板，索引值从0开始算。</param>
        /// <param name="atLeft">是否在左侧插入。默认为真。</param>
        public bool InsertColumn(GridPanel gridPanel, ModifingItem mi, bool atLeft = true)
        {
            if (gridPanel == null) return false;

            Action actColumnsCount = new Action(this.ExID, -1, this.GetType().Name,
                "ColumnsCount", ColumnsCount.ToString(), (ColumnsCount + 1).ToString());

            ColumnsCount += 1;

            mi.Add(actColumnsCount);

            int newColumnIndex = gridPanel.GridX;
            if (atLeft == false)
            {
                // 在当前行底侧插入新行。
                newColumnIndex = newColumnIndex + gridPanel.GridXSpan;
            }

            foreach (UIElement ue in baseGrid.Children)
            {
                GridPanel gp = ue as Expressions.GridPanel;

                if (gp != null && gp.GridX >= newColumnIndex)
                {
                    Action actGridX = new Action(gp.ExID, -1, gp.GetType().Name,
                        "GridX", gp.GridX.ToString(), (gp.GridX + 1).ToString());
                    gp.GridX += 1;
                    mi.Add(actGridX);
                }// 腾出空的列索引。
            }

            for (int i = 0; i < linesCount; i++)
            {
                this.XmlData.LastChild.InsertXml(
                    LunarPresentation.Properties.Resources.GridPanel);

                GridPanel gp = new GridPanel
                    (this.RootPanel, ParentPanel, this.Editor, this)
                {
                    XmlData = XmlData.LastChild,
                    GridX = newColumnIndex,
                    GridY = i
                };

                Action actInsertGridPanel = new Action(gp.ExID, baseGrid.Children.IndexOf(gp),
                   gp.GetType().Name, "InsertGridPanel",
                   null, gp.XmlData.OuterXml, ActionType.InsertGridPanel,
                   this.ExID);
                Action actGridX = new Action(gp.ExID, -1, gp.GetType().Name,
                    "GridX", gp.GridX.ToString(), newColumnIndex.ToString());
                Action actGridY = new Action(gp.ExID, -1, gp.GetType().Name,
                    "GridY", gp.GridY.ToString(), i.ToString());
                mi.Add(actInsertGridPanel);
                mi.Add(actGridX);
                mi.Add(actGridY);

                baseGrid.Children.Add(gp);
                subPanels.Add(gp);
            }

            // 先取原位置这一列的各子面板。
            for (int ic = 0; ic < columnsCount; ic++)
            {
                //遍历每一行中每一个合并单元格。
                for (int il = 0; il < linesCount; il++)
                {
                    GridPanel gp = GetGridPanel(ic, il);
                    if (gp.MergeStanding == GridPanel.Standing.Master)
                    {
                        if (gp.GridX < newColumnIndex &&
                            gp.GridX + gp.GridXSpan - 1 >= newColumnIndex)
                        {
                            GridPanel newBrother = GetGridPanel(newColumnIndex, il);

                            Action actMergeStanding = new Action(newBrother.ExID, -1,
                                newBrother.GetType().Name, "MergeStanding",
                                newBrother.MergeStanding.ToString(),
                                GridPanel.Standing.Slave.ToString());

                            Action actMasterX = new Action(newBrother.ExID, -1, newBrother.GetType().Name,
                                "MasterX", newBrother.MasterX.ToString(), gp.GridX.ToString());

                            Action actMasterY = new Action(newBrother.ExID, -1, newBrother.GetType().Name,
                                "MasterY", newBrother.MasterY.ToString(), gp.GridY.ToString());

                            Action actGridXSpan = new Action(gp.ExID, -1, gp.GetType().Name,
                                "GridXSpan", gp.GridXSpan.ToString(), (gp.GridXSpan + 1).ToString());

                            newBrother.MergeStanding = GridPanel.Standing.Slave;
                            gp.GridXSpan += 1;
                            newBrother.MasterX = gp.GridX;
                            newBrother.MasterY = gp.GridY;

                            mi.Add(actMergeStanding);
                            mi.Add(actMasterX);
                            mi.Add(actMasterY);
                            mi.Add(actGridXSpan);

                            break;
                        }
                    }
                }
            }

            Editor.IsModified = true;
            return true;
        }

        /// <summary>
        /// 删除指定索引的行。
        /// </summary>
        /// <param name="lineIndex">行索引。</param>
        public bool DeleteLine(int lineIndex, ModifingItem mi)
        {
            if (baseGrid == null || baseGrid.Children.Count <= 0 || mi == null) return false;

            for (int i = baseGrid.Children.Count - 1; i >= 0; i--)
            {
                GridPanel gp = baseGrid.Children[i] as GridPanel;
                if (gp.GridY == lineIndex)
                {
                    if (gp.MergeStanding == GridPanel.Standing.Master)
                    {
                        System.Windows.MessageBox.Show(
                            "要删除的行中包含合并单元格，请先拆分之后再执行“删除行”操作！",
                            Globals.appName, System.Windows.MessageBoxButton.OK,
                            System.Windows.MessageBoxImage.Warning);
                        return false;
                    }
                }
            }

            List<GridPanel> masterPanels = new List<GridPanel>();
            //用以阻止重复减GridYSpan。
            for (int i = baseGrid.Children.Count - 1; i >= 0; i--)
            {
                GridPanel gp = baseGrid.Children[i] as GridPanel;
                if (gp.GridY == lineIndex)
                {
                    if (gp.MergeStanding == GridPanel.Standing.Slave)
                    {
                        GridPanel masterPanel = gp.MasterGridPanel;
                        if (masterPanels.Contains<GridPanel>(masterPanel) == false)
                        {
                            masterPanels.Add(masterPanel);

                            Action actMasterPanelGridYSpan = new Action(
                                masterPanel.ExID, -1, masterPanel.GetType().Name,
                                "GridYSpan", masterPanel.GridYSpan.ToString(),
                                (masterPanel.GridYSpan - 1).ToString());

                            masterPanel.GridYSpan -= 1;

                            mi.Add(actMasterPanelGridYSpan);

                            if (masterPanel.GridYSpan == 1 && masterPanel.GridXSpan == 1)
                            {
                                Action actMasterPanelMergeStanding = new Action(
                                    masterPanel.ExID, -1, masterPanel.GetType().Name,
                                    "MergeStanding", masterPanel.MergeStanding.ToString(),
                                    GridPanel.Standing.Normal.ToString());

                                masterPanel.MergeStanding = GridPanel.Standing.Normal;

                                mi.Add(actMasterPanelMergeStanding);
                            }
                        }
                    }
                }
            }

            for (int i = baseGrid.Children.Count - 1; i >= 0; i--)
            {
                GridPanel gp = baseGrid.Children[i] as GridPanel;
                if (gp.GridY == lineIndex)
                {
                    Action actDelGridPanel = new Action(gp.ExID, -1,
                        gp.GetType().Name, "DeleteGridPanel",
                        gp.XmlData.OuterXml, null, ActionType.DeleteGridPanel,
                        gp.ParentExpression.ExID);

                    if (gp.XmlData != null && gp.XmlData.ParentNode != null)
                    {
                        gp.XmlData.ParentNode.RemoveChild(gp.XmlData);
                    }

                    baseGrid.Children.RemoveAt(i);

                    if (this.SubPanels != null && this.SubPanels.Contains(gp))
                    {
                        this.SubPanels.Remove(gp);
                    }

                    mi.Add(actDelGridPanel);
                }
            }

            for (int i = baseGrid.Children.Count - 1; i >= 0; i--)
            {
                GridPanel gp = baseGrid.Children[i] as GridPanel;
                if (gp.GridY > lineIndex)
                {
                    Action actGridY = new Action(gp.ExID, -1, gp.GetType().Name,
                        "GridY", gp.GridY.ToString(), (gp.GridY - 1).ToString());

                    gp.GridY -= 1;

                    mi.Add(actGridY);
                }
            }

            Action actLinesCount = new Action(this.ExID, -1,
                this.GetType().Name, "LinesCount",
                LinesCount.ToString(), (LinesCount - 1).ToString());

            LinesCount -= 1;

            mi.Add(actLinesCount);



            Editor.IsModified = true;
            return true;
        }

        /// <summary>
        /// 删除指定面板所在的行。
        /// </summary>
        /// <param name="gp">指定目标位置的面板。该面板与同行面板均将被删除。</param>
        public bool DeleteLine(GridPanel gp, ModifingItem mi)
        {
            int x = gp.GridX, y = gp.GridY;

            bool result = DeleteLine(gp.GridY, mi);

            //只有在此处才能处理删除后选取哪个子面板的问题。
            if (result)
            {
                Expressions.GridPanel newSelPanel = this.GetGridPanel(x, y);
                if (newSelPanel == null)
                {
                    newSelPanel = this.GetGridPanel(x, y - 1);

                    if (newSelPanel.MergeStanding == Expressions.GridPanel.Standing.Slave)
                    {
                        newSelPanel = this.GetGridPanel(newSelPanel.MasterX, newSelPanel.MasterY);
                    }
                }

                if (newSelPanel != null)
                {
                    mi.NewSelectedExID = newSelPanel.ExID;
                    editor.SelectedExpression = newSelPanel;
                }
            }

            return result;
        }

        /// <summary>
        /// 删除指定索引的列。
        /// </summary>
        /// <param name="columnIndex">列索引。</param>
        public bool DeleteColumn(int columnIndex, ModifingItem mi)
        {
            if (baseGrid == null || baseGrid.Children.Count <= 0 || mi == null) return false;

            for (int i = baseGrid.Children.Count - 1; i >= 0; i--)
            {
                GridPanel gp = baseGrid.Children[i] as GridPanel;
                if (gp.GridX == columnIndex)
                {
                    if (gp.MergeStanding == GridPanel.Standing.Master)
                    {
                        System.Windows.MessageBox.Show(
                            "要删除的列中包含合并单元格，请先拆分之后再执行“删除列”操作！",
                            Globals.appName, System.Windows.MessageBoxButton.OK,
                            System.Windows.MessageBoxImage.Warning);
                        return false;
                    }
                }
            }

            List<GridPanel> masterPanels = new List<GridPanel>();
            //用以阻止重复减GridXSpan。
            for (int i = baseGrid.Children.Count - 1; i >= 0; i--)
            {
                GridPanel gp = baseGrid.Children[i] as GridPanel;
                if (gp.GridX == columnIndex)
                {
                    if (gp.MergeStanding == GridPanel.Standing.Slave)
                    {
                        GridPanel masterPanel = gp.MasterGridPanel;
                        if (masterPanels.Contains<GridPanel>(masterPanel) == false)
                        {
                            masterPanels.Add(masterPanel);

                            Action actMasterPanelGridXSpan = new Action(
                               masterPanel.ExID, -1, masterPanel.GetType().Name,
                               "GridXSpan", masterPanel.GridXSpan.ToString(),
                               (masterPanel.GridXSpan - 1).ToString());

                            masterPanel.GridXSpan -= 1;

                            mi.Add(actMasterPanelGridXSpan);

                            if (masterPanel.GridYSpan == 1 && masterPanel.GridXSpan == 1)
                            {
                                Action actMasterPanelMergeStanding = new Action(
                                    masterPanel.ExID, -1, masterPanel.GetType().Name,
                                    "MergeStanding", masterPanel.MergeStanding.ToString(),
                                    GridPanel.Standing.Normal.ToString());

                                masterPanel.MergeStanding = GridPanel.Standing.Normal;

                                mi.Add(actMasterPanelMergeStanding);
                            }
                        }
                    }
                }
            }

            for (int i = baseGrid.Children.Count - 1; i >= 0; i--)
            {
                GridPanel gp = baseGrid.Children[i] as GridPanel;
                if (gp.GridX == columnIndex)
                {
                    Action ActDelGridPanel = new Action(gp.ExID, -1,
                        gp.GetType().Name, "DeleteGridPanel",
                        gp.XmlData.OuterXml, null, ActionType.DeleteGridPanel,
                        gp.ParentExpression.ExID);

                    if (gp.XmlData != null && gp.XmlData.ParentNode != null)
                    {
                        gp.XmlData.ParentNode.RemoveChild(gp.XmlData);
                    }

                    baseGrid.Children.RemoveAt(i);

                    if (this.SubPanels != null && this.SubPanels.Contains(gp))
                    {
                        this.SubPanels.Remove(gp);
                    }

                    mi.Add(ActDelGridPanel);
                }
            }

            for (int i = baseGrid.Children.Count - 1; i >= 0; i--)
            {
                GridPanel gp = baseGrid.Children[i] as GridPanel;
                if (gp.GridX > columnIndex)
                {
                    Action ActGridX = new Action(gp.ExID, -1, gp.GetType().Name,
                        "GridX", gp.GridX.ToString(), (gp.GridX - 1).ToString());

                    gp.GridX -= 1;

                    mi.Add(ActGridX);
                }
            }

            Action actColumnsCount = new Action(this.ExID, -1,
                this.GetType().Name, "ColumnsCount",
                ColumnsCount.ToString(), (ColumnsCount - 1).ToString());

            ColumnsCount -= 1;

            mi.Add(actColumnsCount);

            Editor.IsModified = true;
            return true;
        }

        /// <summary>
        /// 删除指定面板所在的列。
        /// </summary>
        /// <param name="gp">指定目标位置的面板。该面板与同列面板均将被删除。</param>
        public bool DeleteColumn(GridPanel gp, ModifingItem mi)
        {
            int x = gp.GridX, y = gp.GridY;

            bool result = DeleteColumn(gp.GridX, mi);

            //只有在此处才能处理删除后选取哪个子面板的问题。
            if (result)
            {
                Expressions.GridPanel newSelPanel = this.GetGridPanel(x, y);
                if (newSelPanel == null)
                {
                    newSelPanel = this.GetGridPanel(x - 1, y);

                    if (newSelPanel.MergeStanding == Expressions.GridPanel.Standing.Slave)
                    {
                        newSelPanel = this.GetGridPanel(newSelPanel.MasterX, newSelPanel.MasterY);
                    }
                }

                if (newSelPanel != null)
                {
                    mi.NewSelectedExID = newSelPanel.ExID;
                    editor.SelectedExpression = newSelPanel;
                }
            }

            return result;
        }

        public override string CommentText
        {
            get
            {
                return base.CommentText;
            }
            set
            {
                base.CommentText = value;
                if (isCollapsed && exCollapseMark != null)
                {
                    exCollapseMark.RefreshExCollpseMarkText();
                }
            }
        }

        #region ICollpased接口的实现代码。

        private ExCollapseMark exCollapseMark;

        private bool isCollapsed = false;

        public bool IsCollapsed
        {
            get { return isCollapsed; }
            set
            {
                isCollapsed = value;
                RefreshIsCollapsed();

                this.XmlData.SetAttribute("IsCollapsed", isCollapsed.ToString());

                Editor.IsModified = true;
            }
        }

        private void RefreshIsCollapsed()
        {
            if (isCollapsed)
            {
                if (exCollapseMark == null)
                {
                    exCollapseMark = new ExCollapseMark(this);
                }

                exCollapseMark.RefreshExCollpseMarkText();
                this.mainBorder.Child = exCollapseMark;
            }
            else
            {
                this.mainBorder.Child = baseGrid;
                this.exCollapseMark = null;
            }

            this.InvalidateVisual();
        }

        #endregion

        public override void UpdateExForegroundWithoutXmlChanging(Brush value)
        {
            base.UpdateExForegroundWithoutXmlChanging(value);

            base.exForeground = value;

            if (this.exCollapseMark != null)
            {
                this.exCollapseMark.UpdateForeground();
            }
            else
            {
                RefreshDefBorderColor();
            }
        }

        public override void SetProperty(string propertyName, string value)
        {
            base.SetProperty(propertyName, value);

            switch (propertyName)
            {
                //case "Indent":
                //    {
                //        this.Indent = int.Parse(value);
                //        break;
                //    }
                case "SwitchLineAndColumn":
                    {
                        Commands.Command.RunSwitchLineAndColumn(this);
                        break;
                    }
                case "BorderWidth":
                    {
                        UpdateExForegroundWithoutXmlChanging(this.borderColor);
                        break;
                    }
                case "IsCollapsed":
                    {
                        this.IsCollapsed = bool.Parse(value);
                        break;
                    }
                case "LinesCount":
                    {
                        this.LinesCount = int.Parse(value);
                        break;
                    }
                case "ColumnsCount":
                    {
                        this.ColumnsCount = int.Parse(value);
                        break;
                    }
                case "BorderColor":
                    {
                        if (value == "UnKnown")
                        {
                            this.XmlData.RemoveAttributeByName("BorderColor");
                        }

                        RefreshDefBorderColor();
                        break;
                    }
            }
        }
    }
}
